import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

import java.io.*;
import java.util.*;

public class TestWheelScale extends JFrame {
    JPanel canvas = new Canvas();
    AffineTransform t = new AffineTransform();
    double x = 0.0, y = 0.0;
    double prev_x = 0.0, prev_y = 0.0;
    double rate = 1.0;
    Color bgc = new Color(240, 240, 240);
    Random r = new Random(System.currentTimeMillis());
    MapBinaryData mbd;
    int d = 20;
    Color[] city_colors;
    Color[] city_colors_formal;
    byte[][] temp_is_capital;
    boolean mode = true;
    private final Color lab2rgb(double l, double a, double b_) { // usable or not is remain unseen
        double y = l, x = y + a, z = y - b_;
        if (x > 0.206893) x = x * x * x;
        else x = (x * 116 - 16) / 903.3;
        if (y > 0.206893) y = y * y * y;
        else y = (y * 116 - 16) / 903.3;
        if (z > 0.206893) z = z * z * z;
        else z = (z * 116 - 16) / 903.3;
        double x_ref_white = 0.95047, y_ref_white = 1.0, z_ref_white = 1.08883;
        x *= x_ref_white; y *= y_ref_white; z *= z_ref_white;
        double r = x * 3.240481 + y * -1.537152 + z * -0.498536;
        double g = x * -0.969255 + y * 1.875990 + z * 0.041556;
        double b = x * 0.055647 + y * -0.204041 + z * 1.057311;
        if (r > 0.0031308) r = 1.055 * Math.pow(r, 1 / 2.4) - 0.055;
        else r *= 12.92;
        if (g > 0.0031308) g = 1.055 * Math.pow(g, 1 / 2.4) - 0.055;
        else g *= 12.92;
        if (b > 0.0031308) b = 1.055 * Math.pow(b, 1 / 2.4) - 0.055;
        else b *= 12.92;
        r = Math.max(0, Math.min(r, 1)) * 255;
        g = Math.max(0, Math.min(g, 1)) * 255;
        b = Math.max(0, Math.min(b, 1)) * 255;
        return new Color((int) (r + 0.5), (int) (g + 0.5), (int) (b + 0.5));
    }
    public Color randomColor() {
        return lab2rgb(0.7 - (r.nextInt(0x0721) % 3) * 0.2 * 100, Math.sin(Math.random() * 6.28) * 127, Math.cos(Math.random() * 6.28) * 127);
    }
    private void initialize() {
        setSize(615, 315);
        setVisible(true);
        setDefaultCloseOperation(3);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                prev_x = prev_y = 0.0;
            }
        });
        addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                if (prev_x != 0.0) x += e.getX() - prev_x;
                if (prev_y != 0.0) y += e.getY() - prev_y;
                prev_x = e.getX();
                prev_y = e.getY();
                canvas.repaint();
            }
        });
        addMouseWheelListener(new MouseWheelListener() {
            public void mouseWheelMoved(MouseWheelEvent e) {
                rate -= 0.1 * e.getWheelRotation();
                if (rate < 0.1) rate = 0.1;
                canvas.repaint();
            }
        });
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_X) mode = !mode;
                canvas.repaint();
            }
        });
        add(canvas);
    }
    public void go() {
        try {
            MBDReader reader = new MBDReader(new File("test.mbd"));
            mbd = reader.read();
            System.out.printf("Blocks: %d\n", mbd.block_cnt);
            System.out.printf("Cities: %d\n", mbd.city_cnt);
            System.out.printf("Countries: %d\n", mbd.country_cnt);
            System.out.printf("Factions: %d\n", mbd.faction_cnt);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        city_colors = new Color[mbd.city_cnt];
        city_colors_formal = new Color[mbd.city_cnt];
        for (int i = 0; i < mbd.city_cnt; i++) {
            city_colors[i] = randomColor();
            MapBinaryData.Country c = mbd.countries[mbd.cities[i].belongCountry];
            int r = (c.red + 255) % 255, g = (c.green + 255) % 255, b = (c.blue + 255) % 255;
            city_colors_formal[i] = new Color(r, g, b);
        }
        temp_is_capital = new byte[mbd.width][mbd.height];
        for (int i = 0; i < mbd.width; i++) {
            for (int j = 0; j < mbd.height; j++) {
                temp_is_capital[i][j] = 0;
            }
        }
        for (int i = 0; i < mbd.city_cnt; i++) {
            short x = mbd.cities[i].capitalx, y = mbd.cities[i].capitaly;
            temp_is_capital[y][x] = 1;
        }
        for (int i = 0; i < mbd.country_cnt; i++) {
            short capital = mbd.countries[i].capital;
            short x = mbd.cities[capital].capitalx, y = mbd.cities[capital].capitaly;
            temp_is_capital[y][x] = 2;
        }
        initialize();
    }
    public static void main(String[] args) {
        new TestWheelScale().go();
    }
    public class Canvas extends JPanel {
        @Override
        public void paint(Graphics g) {
            int w = mbd.width * d, h = mbd.height * d;
            Graphics2D g2d = (Graphics2D) g;
            g2d.setPaint(Color.BLACK);
            Color prev = (Color) g2d.getPaint();
            g2d.setPaint(bgc);
            g2d.fillRect(0, 0, 600, 300);
            g2d.setPaint(prev);
            super.paint(g);
            if (!(g2d.getTransform() instanceof AffineTransform)) {
                t = new AffineTransform();
            }
            AffineTransform trans = new AffineTransform(t);
            trans.translate(x, y);
            trans.scale(rate, rate);
            g2d.setTransform(trans);
            super.paint(g);
            g2d.setStroke(new BasicStroke(2.0f));
            for (int x = 0; x < w; x += d) {
                for (int y = 0; y < h; y += d) {
                    g2d.drawRect(x, y, d, d);
                }
            }
            g2d.setStroke(new BasicStroke(1.0f));
            for (int x = 0; x < w; x += d) {
                for (int y = 0; y < h; y += d) {
                    int block_id = (x / d) + (y / d) * mbd.width;
                    int city_id = mbd.blocks[block_id].belongCity;
                    if (mode) g2d.setPaint(city_colors_formal[city_id]);
                    else g2d.setPaint(city_colors[city_id]);
                    g2d.fillRect(x + 1, y + 1, d - 1, d - 1);
                    if (temp_is_capital[x / d][y / d] == 1) {
                        g2d.setPaint(new Color(96, 96, 96));
                        g2d.fillRect(x + d / 4, y + d / 4, d / 2, d / 2);
                        g2d.setPaint(city_colors_formal[city_id]);
                    } else if (temp_is_capital[x / d][y / d] == 2) {
                        g2d.setPaint(prev);
                        g2d.fillRect(x + d / 4, y + d / 4, d / 2, d / 2);
                        g2d.setPaint(city_colors_formal[city_id]);
                    }
                }
            }
            g2d.setPaint(prev);
        }
    }
}